#include "vector.h"

template<class T>
typename clx::vector<T>::iterator clx::vector<T>::begin()
{
  return _start;
}

template<class T>
typename clx::vector<T>::iterator clx::vector<T>::end()
{
  return _finish;
}

template<class T>
typename clx::vector<T>::const_iterator clx::vector<T>::begin() const
{
  return _start;
}

template<class T>
typename clx::vector<T>::const_iterator clx::vector<T>::end() const
{
  return _finish;
}

template<class T>
void clx::vector<T>::my_swap(vector<T>& v)
{
  ::swap(_start, v._start);
  ::swap(_finish, v._finish);
  ::swap(_endofstorage, v._endofstorage);
}

template<class T>
clx::vector<T>::vector()
  :_start(nullptr)
  ,_finish(nullptr)
  ,_endofstorage(nullptr)
{}

template<class T>
clx::vector<T>::vector(const vector<T>& v)
  :_start(nullptr)
  ,_finish(nullptr)
  ,_endofstorage(nullptr)
{
  reserve(v.capacity());
  for (auto e : v)
  {
    push_back(e);
  }
}

template<class T>
clx::vector<T>& clx::vector<T>::operator=(vector<T> v)
{
  swap(v);
  return *this;
}

template<class T>
clx::vector<T>::~vector()
{
  if (_start)
  {
    delete[] _start;
  }
  _start = _finish = _endofstorage = nullptr;
}


template<class T>
size_t clx::vector<T>::size() const
{
  return _finish - _start;
}

template<class T>
size_t clx::vector<T>::capacity() const
{
  return _endofstorage - _start;
}

template<class T>
void clx::vector<T>::reserve(size_t n)
{
  if (n > capacity())
  {
    iterator tmp = new T[n];
      size_t sz = size();
      for (size_t i = 0; i < size(); i++)
      {
        tmp[i] = _start[i];
      }
      delete[] _start;
      _start = tmp;
      _finish = _start + sz;
      _endofstorage = _start + n;
  }
}

template<class T>
void clx::vector<T>::resize(size_t n, const T& val)
{
  if (n > capacity())
  {
    reserve(n);
  }
  if (n > size())
  {
    iterator it = _finish;
    while (_finish != _endofstorage)
    {
      *it = val;
      it++;
    }
  }
  if (n < size())
  {
    _finish = _start + n;
  }
}

template<class T>
void clx::vector_print(const vector<T>& v)
{
  typename vector<T>::const_iterator it = v.begin();
  while (it != v.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
}

template<class T>
bool clx::vector<T>::empty() const 
{
  return size() == 0;
}

template<class T>
void clx::vector<T>::push_back(const T& val)
{
  if (_endofstorage == _finish )
  {
    size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
    reserve(newcapacity);
  }
  *_finish = val;
  _finish++;

}

template<class T>
void clx::vector<T>::pop_back()
{
  if (!empty())
  {
    _finish--;
  }
}

void clx::vector_test1()
{
  vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  vector_print(v);
}


template<class T>
void clx::vector<T>::insert(iterator pos, const T& val)
{
  size_t sz = pos - _start;    
  if (_finish == _endofstorage)
  {
    size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
    reserve(newcapacity);
    pos = _start + sz;
  }
  iterator end = _finish;
  while (end != pos)
  {
    *end = *(end - 1);
    end--;
  }
  *pos = val;
  _finish++;
}

template<class T>
typename clx::vector<T>::iterator clx::vector<T>::erase(iterator pos)
{
  assert(!empty());
  iterator it = pos;
  while (pos < _finish - 1)
  {
    *it = *(it + 1);
  }
  _finish--;
  return pos;
}

void clx::vector_test2()
{
  vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  vector_print(v);
  vector<int>::iterator pos = find(v.begin(), v.end(), 4);
  v.insert(pos, 5);
  vector_print(v);
  
}

template<class T>
const T& clx::vector<T>::operator[](size_t i) const
{
  assert(i < size());
  return *(_start + i);
}

template<class T>
T& clx::vector<T>::operator[](size_t i) 
{
  assert(i < size());
  return *(_start + i);
}

void clx::vector_test3()
{
  vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  for (size_t i = 0; i < v.size() - 1; i++)
  {
    cout << v[i] << " ";
  }
  cout << endl;
}











